﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;

using Microsoft.Xna.Framework.Media;

namespace Coding4Fun.SlideShow
{
    public partial class Slide : UserControl
    {
        /// <summary>
        /// The current storyboard that was chosen randomly from storyboardList
        /// </summary>
        private Storyboard _currentStoryboard = new Storyboard();

        /// <summary>
        /// Gets the current time of the currentStoryboard before it was stopped
        /// </summary>
        public TimeSpan TimeStoryboardStopped;

        /// <summary>
        /// Gets the Orientation for which to display the image based on the Image's ratio
        /// </summary>
        protected Orientation ImageOrientation = Orientation.Horizontal;
        
        /// <summary>
        /// Gets or sets the picture for the Image within the Slide
        /// </summary>
        public void SetImage(ImageSource image)
        {
            //ImageOrientation = (image.PixelWidth > image.PixelHeight)
            //                       ? Orientation.Horizontal
            //                       : Orientation.Vertical;
            //var targetImg = (ImageOrientation == Orientation.Horizontal) ? uxHorizontalImage : uxVerticalImage;

            // Sets the Image Source and Image Visibility based on the Orientation
            uxHorizontalImage.Visibility = Visibility.Collapsed;
            //uxVerticalImage.Visibility = Visibility.Collapsed;

            uxHorizontalImage.Source = image;
            uxHorizontalImage.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Usercontrol Constructor
        /// </summary>
        public Slide()
        {
            // Required to initialize variables
            InitializeComponent();

            uxSBOutro.Completed += uxSBOutro_Completed;
            uxSBPanning.Completed += uxSBSlideDuration_Completed;
            uxSBZoomming.Completed += uxSBSlideDuration_Completed;
        }

        private void SetStoryboardTimes(Storyboard target, TimeSpan duration, TimeSpan hold, bool isZooming)
        {
            target.Duration = duration + hold;

            foreach (var child in
                target.Children.Cast<DoubleAnimationUsingKeyFrames>().Where(child => child.KeyFrames.Count == 2))
            {
                child.KeyFrames[1].KeyTime = duration;

                // randomly flip numbers
                if (!isZooming && App.RandomNumber.Next(0, 2) != 0)
                    continue;

                SwapKeyFrameValues(child);
            }
            
            // zooming, valid grouping, and should I randomly flip values
            if (isZooming && target.Children.Count % 2 == 0 && App.RandomNumber.Next(0, 2) != 0)
            {
                var groupings = target.Children.Cast<DoubleAnimationUsingKeyFrames>().GroupBy(o => (string)o.ReadLocalValue(Storyboard.TargetNameProperty));

                foreach (var group in groupings)
                {
                    var startValue = group.ElementAt(0).KeyFrames[0].Value;
                    var endValue = group.ElementAt(0).KeyFrames[1].Value;

                    foreach (var item in group)
                    {
                        item.KeyFrames[0].Value = endValue;
                        item.KeyFrames[1].Value = startValue;
                    }
                }
            }
        }

        private static void SwapKeyFrameValues(DoubleAnimationUsingKeyFrames frame)
        {
            var temp = frame.KeyFrames[0].Value;

            frame.KeyFrames[0].Value = frame.KeyFrames[1].Value;
            frame.KeyFrames[1].Value = temp;
        }

        /// <summary>
        /// Event handler that fires when the Slide Duration has completed
        /// Calls the SlideDurationCompleting Event
        /// </summary>
        void uxSBSlideDuration_Completed(object sender, EventArgs e)
        {
            if (App.SlideDurationCompleting != null)
                App.SlideDurationCompleting(sender, e);
        }


        /// <summary>
        /// Event handler that fires when the outro has completed
        /// Stops the Slide and removes the usercontrol from the Slide Grid on the player
        /// </summary>
        void uxSBOutro_Completed(object sender, EventArgs e)
        {
            ForceRemove();
        }

        public void ForceRemove()
        {
            Stop();
            if (!(Parent is Grid))
                return;

            ((Grid)Parent).Children.Remove(this);
            GC.Collect();
        }

        /// <summary>
        /// Begins Slide
        /// </summary>
        public void Begin()
        {
            var duration = TimeSpan.FromSeconds(SettingsHelper.SlideDuration);
            var hold = TimeSpan.FromSeconds(SettingsHelper.HoldDuration);

            var isZooming = (App.RandomNumber.Next(0, 3) == 0);  // total 4 different style pans, 2 zoom, 1/3 chance to zoom
            _currentStoryboard = isZooming ? uxSBZoomming : uxSBPanning;

            SetStoryboardTimes(_currentStoryboard, duration, hold, isZooming);

            // Begin Intro and Current Storyboard
            _currentStoryboard.Begin();
        }


        /// <summary>
        /// Pauses all Storyboards
        /// </summary>
        public void Pause()
        {
            TimeStoryboardStopped = _currentStoryboard.GetCurrentTime();
            _currentStoryboard.Stop();

            uxSBOutro.Pause();
        }

        /// <summary>
        /// Resumes all Storyboards
        /// </summary>
        public void Resume()
        {
            _currentStoryboard.Begin();
            _currentStoryboard.Seek(TimeStoryboardStopped);

            uxSBOutro.Resume();
        }

        /// <summary>
        /// Stops all Storyboards
        /// </summary>
        public void Stop()
        {
            _currentStoryboard.Stop();
            uxSBOutro.Stop();
        }
    }
}
